#include "http.hpp"

#define WWWROOT "./wwwroot"

std::string getRequestStr(HttpRequest& req)
{
    std::string req_str;
    req_str += req._method + " " + req._path + " " + req._version + "\r\n";
    for (auto& parm : req._params)
        req_str += parm.first + ": " + parm.second + "\r\n";
    for (auto& header : req._headers)
        req_str += header.first + ": " + header.second + "\r\n";
    req_str += "\r\n";
    req_str += req._body;
    return req_str;
}

void echo(HttpRequest& req, HttpResponse& res)
{
    res.setContent(getRequestStr(req), "text/plain");
}

void login(HttpRequest& req, HttpResponse& res)
{
    res.setContent(getRequestStr(req), "text/plain");
}

void putFile(HttpRequest& req, HttpResponse& res)
{
    std::string filename = WWWROOT + req._path;//./wwwroot/123.txt
    Util::writeFile(filename, req._body);
}

void delFile(HttpRequest& req, HttpResponse& res)
{
    res.setContent(getRequestStr(req), "text/plain");
}

int main()
{
    // std::string s = "abc,efg,,,hig,,";
    // std::vector<std::string> subs;
    // Util::split(s, ",", subs);
    // for (auto& s : subs)
    //     std::cout << s << std::endl;

    // std::string buf;
    // if (!Util::readFile("../log.hpp", buf))
    //     exit(-1);
    // std::cout << buf << std::endl;
    // if (!Util::writeFile("./test.txt", buf))
    //     exit(-1);

    // std::string url = "C  ";
    // std::string encode = Util::urlEncode(url, true);
    // std::string decode = Util::urlDecode(encode, true);
    // std::cout << encode << std::endl;
    // std::cout << decode << std::endl;

    // std::cout << Util::statusDesc(200) << std::endl;
    // std::cout << Util::statusDesc(404) << std::endl;
    // std::cout << Util::statusDesc(800) << std::endl;
    // std::cout << Util::extMime("123.png") << std::endl;
    // std::cout << Util::extMime("456.txt") << std::endl;
    // std::cout << Util::extMime("789.xxx") << std::endl;

    // std::cout << Util::isDirectory("test") << std::endl;
    // std::cout << Util::isDirectory("../echo") << std::endl;
    // std::cout << Util::isRegular("test") << std::endl;
    // std::cout << Util::isRegular("../echo") << std::endl;

    // std::cout << Util::isValidPath("/html/index.html") << std::endl;//level == 2
    // std::cout << Util::isValidPath("/image/../html/index.html") << std::endl;//level == 2
    // std::cout << Util::isValidPath("/image/../html/../../index.html") << std::endl;//level == -1

    HttpServer server(8080);
    server.setBaseDir(WWWROOT);//设置静态资源根目录 所有静态资源请求的文件都在该目录下查找
    server.Get("/echo", echo);
    server.Post("/login", login);
    server.Put("/123.txt", putFile);
    server.Delete("/123.txt", delFile);
    server.start();

    //TODO
    /*
    1. postman put/delete 功能性请求测试
    2. 创建客户端 每隔3s向服务器发送一条完整请求并接收响应 测试服务器长连接通信超时自动关闭连接
    3. 客户端发送一条不完整请求后不再发送请求 测试服务器等待客户端下一轮数据到来无果后 超时关闭连接
    4. 客户端发送多条不完整请求(主要针对请求正文不完整) 第一条之后的请求会作为第一条请求的正文 服务器返回一条完整响应和一条错误页面响应
    5. 服务器对一个连接的业务处理的时间较长 导致后续连接一直得不到处理后超时 当第一个连接的事件处理完成后 下一轮事件处理中
       如果定时器描述符的事件在后续超时连接描述符之前处理 那么会对后续连接进行超时释放 但会等到本轮事件处理结束后再释放
       所以本轮对后续超时连接的处理是无效的 因为处理结束释放连接 后续的事件处理中不会对已经释放的连接进行监控了 响应不会发送给客户端

       定时器描述符事件在第一个连接描述符事件之前处理 秒针走一步无影响 第一个连接事件处理完毕后 后续多个连接同时开启读监控和非活跃释放(runAllTask调用任务池任务)
       接着进入下一轮事件处理 假设本轮处理时 连接描述符事件在定时器描述符事件之前处理 第一个连接的写事件触发返回响应 后续一批连接事件处理完成后(响应还未实际发送) 定时器已经超时很多次了
       因此处理定时器描述符事件时 秒针会向后走很多步 导致第一个连接和后续所有连接全部触发超时关闭任务 本轮事件处理结束后 通过runAllTask释放所有连接
    6. 客户端一次性发送多条完整请求 服务器处理多条请求后 一次性返回多条完整响应
    7. 客户端向服务器发送一个大文件 服务器接收文件内容后 判断客户端文件是否与服务器保存的文件一致(手动通过md5sum判断)
    8. 通过webbench工具对服务器进行性能压力测试 获取并发量(同时处理多少客户端的请求而不出现连接失败)和QPS(每秒钟处理的包的数量 请求数?)两个指标
    */
    return 0;
}